package com.hhdys.action;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.hhdys.annotation.Access;
import com.hhdys.model.Account;
import com.hhdys.model.AccountFuncAss;
import com.hhdys.model.Function;
import com.hhdys.model.MenuTree;
import com.hhdys.service.AccountFuncService;
import com.hhdys.service.AccountService;
import com.hhdys.service.DepartmentService;
import com.hhdys.service.FunctionService;
import com.hhdys.service.MenuTreeService;
import com.hhdys.service.PositionService;
import com.hhdys.service.RoleService;
import com.hhdys.util.Constant;

@Controller
@RequestMapping("/admin")
@Access("用户管理")
public class AccountAction {

	Logger log = LogManager.getLogger(AccountAction.class);
	@Autowired
	private SecurityManager securityManager;
	@Autowired
	private AccountService accountService;
	@Autowired
	private MenuTreeService menuTreeService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private PositionService positionService;
	@Autowired
	private DepartmentService departmentService;
	@Autowired
	private AccountFuncService assService;
	@Autowired
	private FunctionService functionService;

	@RequestMapping("/login")
	public String userLogin(String username, String password,String vCode, Model model) {
		Subject currentUser = SecurityUtils.getSubject();
		Session session=currentUser.getSession();
		if(Constant.KAPTCHASWITCH){//开启验证码
			String sessionCode=(String)session.getAttribute(Constant.KAPTCHA_SESSION_KEY);
			if(!StringUtils.equalsIgnoreCase(sessionCode, vCode)){
				model.addAttribute("msg", "验证码错误！");
				return "admin/login";
			}
		}
		if (!currentUser.isAuthenticated()) {
			UsernamePasswordToken token = new UsernamePasswordToken(username,
					password);
			token.setRememberMe(true);
			try {
				currentUser.login(token);
				Account account = accountService.selAccountByUsernameAndPwd(
						username, password);
				
				session.setAttribute("name", account.getName());
				session.setAttribute("userId", account.getId());
				log.info("用户登陆==用户名："+username+":时间："+DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss"));

				SavedRequest savedRequest = (SavedRequest)session.getAttribute(WebUtils.SAVED_REQUEST_KEY);
				if(savedRequest!=null){
					String redirectUrl=getRedirectUrl(savedRequest.getQueryString());
					if(StringUtils.isNotBlank(redirectUrl)){//如果后缀有url则跳转到此URL
						return "redirect:"+redirectUrl;
					}
					String saveUrl=savedRequest.getRequestUrl();
					if(!StringUtils.endsWithAny(saveUrl,"/admin/","/admin")) {
						return "redirect:" +Constant.getURl()+saveUrl;
					}
				}
			} catch (Exception e) {
				model.addAttribute("msg", "登陆失败，用户名或者密码错误！");
				return "admin/login";
			}
		}
		return "forward:main.do";
	}

	/**
	 * 获取跳转地址
	 * @param queryString 查询参数
     * @return 跳转地址
     */
	private String getRedirectUrl(String queryString){
		String redirectUrl="";
		if(StringUtils.isBlank(queryString)){
			return redirectUrl;
		}
		String[] strs = StringUtils.split(queryString, "&");
		if(ArrayUtils.isEmpty(strs)){
			return redirectUrl;
		}
		for(String str:strs){
			String[] paramStrs=StringUtils.split(str,"=");
			if(ArrayUtils.getLength(paramStrs)<2){
				return redirectUrl;
			}
			return paramStrs[1];
		}
		return redirectUrl;
	}

	@RequestMapping("/main")
	public String main(Model model) {
		Subject curUser = SecurityUtils.getSubject();
		if (!curUser.isAuthenticated()) {
			return "admin/login";
		}
		Session session=curUser.getSession();
		int userId=(Integer)session.getAttribute("userId");
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("lastLoginTime", new Date());
		map.put("id", userId);
		accountService.updateLastLoginTime(map);
		model.addAttribute("tree", menuTreeService.showMenus(0));
		return "admin/main";
	}

	@RequestMapping("/loginOut")
	public String loginOut() {
		Subject currentUser = SecurityUtils.getSubject();
		if(currentUser.isAuthenticated()){
			currentUser.logout();
		}
		return "admin/login";
	}
	
	@RequestMapping("/ajaxLoginOut")
	public void ajaxLoginOut() {
		Subject currentUser = SecurityUtils.getSubject();
		if(currentUser.isAuthenticated()){
			currentUser.logout();
		}
	}

	@RequestMapping("/changePWD")
	@ResponseBody
	public String changePWD(String oldPwd, String reNewPwd) {
		Subject currentUser = SecurityUtils.getSubject();
		Session session = currentUser.getSession();
		if (accountService.updatePwd(reNewPwd, oldPwd,
				(Integer) session.getAttribute("userId")) == 1) {
			return "success";
		}
		return "error";
	}

	@RequestMapping("/account/accountIndex")
	@Access("查询")
	public String showAccounts(
			@RequestParam(required = false, defaultValue = "") String username,
			@RequestParam(required = false, defaultValue = "1") int curPage,
			@RequestParam(required = false, defaultValue = "15") int pageSize,
			Model model) {
		model.addAttribute("list",
				accountService.accoutsShow(username, curPage, pageSize));
		model.addAttribute("curPage", curPage);
		model.addAttribute("pageSize", pageSize);
		model.addAttribute("total", accountService.accoutCount(username));
		model.addAttribute("username", username);
		return "admin/account/accountList";
	}

	@RequestMapping("/account/showAdd")
	@Access("添加")
	public String showAdd(Model model) {
		model.addAttribute("roles", roleService.selRoles());
		model.addAttribute("positions", positionService.selPositions());
		model.addAttribute("flag", "addAccount.do");
		model.addAttribute("json", departmentService.showDepartmentsJson());
		return "admin/account/addOrEditAccount";
	}

	@RequestMapping("/account/check")
	@ResponseBody
	public String checkUserName(String username) {
		long count = accountService.getAccountsByUserName(username);
		if (count > 0) {
			return "{\"success\":\"error\",\"msg\":\"用户名已存在，请输入其他用户名！\"}";
		}
		return "{\"success\":\"success\",\"msg\":\"恭喜你可以使用！\"}";
	}

	@RequestMapping("/account/changeStat")
	@ResponseBody
	public String changeStat(int stat, int accountId) {
		if (accountService.changeAccountStat(stat, accountId)) {
			return "success";
		}
		return "error";
	}

	@RequestMapping("/account/addAccount")
	@ResponseBody
	@Access("添加")
	public String addAccount(Account account,Model model) {
		Subject curUser = SecurityUtils.getSubject();
		account.setPasswd(DigestUtils.md5Hex("123456"));
		account.setModifyTime(new Date());
		account.setLastModify((String) curUser.getPrincipal());
		account.setInuse(1);
		if (accountService.addAccount(account)) {
			return "success";
		}
		return "error";
	}

	@RequestMapping("/account/del")
	@ResponseBody
	@Access("删除")
	public String delRole(String ids) {
		accountService.delAccount(ids);
		return "success";
	}

	@RequestMapping("/account/showEdit")
	@Access("编辑")
	public String showEdit(int id,Model model) {
		Account account = accountService.getAccountById(id);
		model.addAttribute("account", account);
		model.addAttribute("flag", "edit.do");

		String json = departmentService.showDepartmentsJson();
		model.addAttribute("json", json);
		model.addAttribute("roles", roleService.selRoles());
		model.addAttribute("positions", positionService.selPositions());
		model.addAttribute("dep",
				departmentService.getDepartmentById(account.getDepartment()));
		return "admin/account/addOrEditAccount";
	}

	@RequestMapping("/account/edit")
	@ResponseBody
	@Access("编辑")
	public String editAccount(Account account, Model model) {
		Subject curUser = SecurityUtils.getSubject();
		account.setModifyTime(new Date());
		account.setLastModify((String) curUser.getPrincipal());
		if (accountService.editAccount(account)) {
			return "success";
		}
		return "error";
	}

	@RequestMapping(value = "/account/menuFunc", produces = "application/json;charset=utf-8")
	@ResponseBody
	public String getMenuFunc() {
		StringBuilder builder = new StringBuilder("[");
		List<MenuTree> menuTrees = sortMenus(menuTreeService.showAllTrees(), 0);
		for (MenuTree tree : menuTrees) {
			String name = tree.getName();
			builder.append("{\"name\":\"" + name + "\",\"func\":[");
			List<Function> functions = functionService
					.getFunctionsByPageId(tree.getId());
			for (Function func : functions) {
				builder.append("{\"name\":\"" + func.getName() + "\",\"id\":"
						+ func.getId() + "},");
			}
			if (functions.size() > 0) {
				builder.deleteCharAt(builder.length() - 1);
			}
			builder.append("]},");
		}
		if (menuTrees.size() > 0) {
			builder.deleteCharAt(builder.length() - 1);
		}
		builder.append("]");
		return builder.toString();
	}

	@RequestMapping("/account/addFuncs")
	@ResponseBody
	public String addRoleFuncs(int accountId, String funcs) {
		assService.addAss(accountId, funcs);
		return "success";
	}

	@RequestMapping("/account/getFuncs")
	@ResponseBody
	public String getFuncs(int accountId) {
		StringBuilder builder = new StringBuilder();
		Set<Integer> set = assService.getAssByAccountId(accountId);
		for (int ass : set) {
			builder.append(ass + ",");
		}
		return builder.toString();
	}

	private List<MenuTree> sortMenus(List<MenuTree> list, int parentId) {
		List<MenuTree> result = new ArrayList<MenuTree>();
		for (MenuTree menu : list) {
			if (menu.getParentId() == parentId) {
				result.add(menu);
				result.addAll(sortMenus(list, menu.getId()));
			}
		}
		return result;
	}

	/**
	 * @return the securityManager
	 */
	public SecurityManager getSecurityManager() {
		return securityManager;
	}

	/**
	 * @param securityManager
	 *            the securityManager to set
	 */
	public void setSecurityManager(SecurityManager securityManager) {
		this.securityManager = securityManager;
	}

	/**
	 * @return the accountService
	 */
	public AccountService getAccountService() {
		return accountService;
	}

	/**
	 * @param accountService
	 *            the accountService to set
	 */
	public void setAccountService(AccountService accountService) {
		this.accountService = accountService;
	}

	/**
	 * @return the menuTreeService
	 */
	public MenuTreeService getMenuTreeService() {
		return menuTreeService;
	}

	/**
	 * @param menuTreeService
	 *            the menuTreeService to set
	 */
	public void setMenuTreeService(MenuTreeService menuTreeService) {
		this.menuTreeService = menuTreeService;
	}

	/**
	 * @return the roleService
	 */
	public RoleService getRoleService() {
		return roleService;
	}

	/**
	 * @param roleService
	 *            the roleService to set
	 */
	public void setRoleService(RoleService roleService) {
		this.roleService = roleService;
	}

	/**
	 * @return the positionService
	 */
	public PositionService getPositionService() {
		return positionService;
	}

	/**
	 * @param positionService
	 *            the positionService to set
	 */
	public void setPositionService(PositionService positionService) {
		this.positionService = positionService;
	}

	/**
	 * @return the departmentService
	 */
	public DepartmentService getDepartmentService() {
		return departmentService;
	}

	/**
	 * @param departmentService
	 *            the departmentService to set
	 */
	public void setDepartmentService(DepartmentService departmentService) {
		this.departmentService = departmentService;
	}

	/**
	 * @return the functionService
	 */
	public FunctionService getFunctionService() {
		return functionService;
	}

	/**
	 * @param functionService
	 *            the functionService to set
	 */
	public void setFunctionService(FunctionService functionService) {
		this.functionService = functionService;
	}

	/**
	 * @return the assService
	 */
	public AccountFuncService getAssService() {
		return assService;
	}

	/**
	 * @param assService
	 *            the assService to set
	 */
	public void setAssService(AccountFuncService assService) {
		this.assService = assService;
	}

}
